//# 主体 拖拽功能实现

 
class DragFile {

    constructor(dragArea, config) {
        this.dragArea = dragArea;
        Object.keys(config).forEach(item => this[item] = config[item]);
        this.filesInfo = [];
        this.init();
    }

    init() {
        this.preventDefault();
        this.dragenter();
        this.dragleave();
        this.noDrop();
    }

    preventDefault() {
        docNode.on({
            drop: ev => ev.preventDefault(),
            dragover: ev => ev.preventDefault(),
        });
        this.dragArea.on('dragover', ev => ev.preventDefault());
    }

    dragenter() {
        let dragArea = this.dragArea,
            dataAttr = this.highlight.dataAttr,
            theme = this.highlight.theme;
        dragArea.on('dragenter', ev => {
            if(ev.relatedTarget === null) return;
            dragArea.attr(dataAttr, theme);
        });
    }

    dragleave() {
        let dragArea = this.dragArea,
            dataAttr = this.highlight.dataAttr;
        dragArea.on('dragleave', () => {
            dragArea.removeAttr(dataAttr);
        });
    }

    noDrop() {
        let dragArea = this.dragArea,
            tips = this.tips;
        docNode.on('drop', ev => {
            ev.target !== dragArea[0] && dragArea.text(tips.failure);
        });
    }

    drop(cb) {
        let dragArea = this.dragArea,
            tips = this.tips;
        dragArea.on('drop', ev => {
            if(ev.dataTransfer.files.length === 0) return;
            dragArea.text(tips.success);
            let newFiles = Array.from(ev.dataTransfer.files),
                newFilesInfoArr = this.getFilesInfo(newFiles);
            this.addAllFilesUrl(newFiles, newFilesInfoArr).then(res => {
                this.filesInfo.push(...newFilesInfoArr);
                cb && cb(newFilesInfoArr);
            });
        });
    }

    getFilesInfo(newFiles) {
        let len = newFiles.length,
            newFilesInfoArr = [];
        for (let i = 0; i < len; i++) {
            let curFile = newFiles[i];
            info(curFile);
            newFilesInfoArr.push({
                lastModified: curFile.lastModified,
                lastModifiedDate: curFile.lastModifiedDate,
                name: curFile.name,
                size: curFile.size,
                type: curFile.type,
            });
        }
        return newFilesInfoArr;
    }

    addAllFilesUrl(newFiles, newFilesInfoArr, cb) {
        let allToBase64 = newFiles.map(file => this.toBase64(file));
        return Promise.all(allToBase64).then(res => {
            info(res)
            
            newFilesInfoArr.forEach((item, i) => item.base64Url = res[i]);
        }, err => {
            info(err);
            this.dragArea.text(this.tips.notFile);
        });
    }

    toBase64(file) {
        return new Promise((resolve, reject) => {
            try {
                let reader = new FileReader();
                reader.onload = ev => resolve(ev.target.result);
                reader.onerror = () => {
                    reject(reader.error);
                    reader.abort();
                }
                
                // reader.readAsText(file)
                reader.readAsDataURL(file);
                //如果不是文件就进入失败状态
            } catch (err) {
                reject(err);
            }
        });
    }

}


let dragArea = $('.drag-area'),
    docNode = $(doc);

//拖拽文件相关配置
let config = {
    highlight: {
        dataAttr: 'data-highlight',
        theme: 'dodgerblue',
    },
    tips: {
        failure: '请拖放到指定区域',
        success: '文件拖拽成功',
        notFile: '拖拽内容不是文件喔~'
    },
}
let dragInstance = new DragFile(dragArea, config);

//渲染拖拽文件信息
let content = $('.content');

function renderNewData(filesInfo) {
    let fragments = new DocumentFragment();
    let allLis = filesInfo.map(item => {
        let li = doc.createElement('li');
        li.innerHTML = `<span>${item.name}</span><span>${item.base64Url}</span><span>${(item.size / 1024).toFixed(2)}KB</span>`;
        return li;
    });
    fragments.append(...allLis);
    content.append(fragments);
}
dragInstance.drop(renderNewData);